#include <assert.h>

#include "interrupt.h"
#include "cond.h"
#include "list.h"
#include "ULT.h"
#include "linkedlist.h"

void Cond_Init(Cond *c, Lock *ls)
{
  interruptsOff();
  c->queue = list_init();
  interruptsOn();
  return;
}

void Cond_Wait(Cond *c, Lock *ls)
{
 volatile int notDone = 1;
 
	Lock_Release(ls);
	interruptsOff();
	getcontext(runThread()->context);
	if (notDone) {
	notDone = 0;
        runThread()->status = WAITING;
	append(c->queue, runThread());
	 
	/* In ULT_Yield, do not add current thread to ready
	list if it's status is WAITING */
	Tid re = ULT_Yield(ULT_ANY);
	assert(ULT_isOKRet(re));
}
 
Lock_Acquire(ls);
}


void Cond_Signal(Cond *c, Lock *ls)
{
interruptsOff();
if (! c->queue->size == 0) {
  ThrdCtlBlk *blk = pop(c->queue);
  append(ls->list, blk);
}
interruptsOn();
}

void Cond_Broadcast(Cond *c, Lock *ls)
{
interruptsOff();
ThrdCtlBlk *blk;
while (! c->queue->size == 0) {
  blk = pop(c->queue);
  append(ls->list, blk);
}
interruptsOn();
}

/*
 * Return 0 on success. 
 * Return negative on failure.
 *    ERR_COND_BUSY -- threads are waiting on this cond
 */
int 
Cond_Destroy(Cond *c)
{
interruptsOff();
if (! c->queue->size == 0) {
interruptsOn();
return -1;
}
interruptsOn();
return 0;
}

